home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / xlib / tprim.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  18.4 KB  |  843 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <GL/glx.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #include <unistd.h>
  21. #include <stdlib.h>
  22. #include <X11/keysym.h>
  23. #include <math.h>
  24. #include <sys/types.h>
  25. #include <time.h>
  26.  
  27. static int RGB_attributes[] = {
  28.     GLX_RGBA,
  29.     GLX_RED_SIZE, 1,
  30.     GLX_GREEN_SIZE, 1,
  31.     GLX_BLUE_SIZE, 1,
  32.     None,
  33. };
  34.  
  35. static int CI_attributes[] = {
  36.     None,
  37. };
  38.  
  39. int rgb = 1;
  40.  
  41. #define PIXEL_CENTER(x) ((long) (x) + 0.5)
  42. #define SETCOLOR(x) (rgb ? glColor3fv(rgbMap[x]) : glIndexf(x))
  43.  
  44. enum {
  45.     BLACK = 0,
  46.     RED,
  47.     GREEN,
  48.     YELLOW,
  49.     BLUE,
  50.     MAGENTA,
  51.     CYAN,
  52.     WHITE
  53. };
  54.  
  55. static float rgbMap[8][3] = {
  56.     {0, 0, 0},
  57.     {1, 0, 0},
  58.     {0, 1, 0},
  59.     {1, 1, 0},
  60.     {0, 0, 1},
  61.     {1, 0, 1},
  62.     {0, 1, 1},
  63.     {1, 1, 1}
  64. };
  65.  
  66.  
  67. #define GAP 10
  68. #define ROWS 3
  69. #define COLS 4
  70.  
  71. static long W = COLS*100 + (COLS + 1)*GAP;
  72. static long H = ROWS*100 + (ROWS + 1)*GAP;
  73. static long boxW = 100;
  74. static long boxH = 100;
  75. static long drawBuffer = GL_FRONT;
  76. static int randomVertex = 0;
  77. static int clipped = 0;
  78. static int fastest2D = 0;
  79. static int xoffset, yoffset;
  80.  
  81. static void Viewport(long row, long column)
  82. {
  83.     long x, y;
  84.  
  85.     x = GAP + column * (boxW + GAP);
  86.     y = GAP + row * (boxH + GAP);
  87.  
  88.     glDrawBuffer(GL_FRONT);
  89.  
  90.     glEnable(GL_SCISSOR_TEST);
  91.     glScissor(x, y, boxW, boxH);
  92.  
  93.     glPushAttrib(GL_COLOR_BUFFER_BIT);
  94.     glColorMask(1, 1, 1, 1);
  95.     glIndexMask(~0);
  96.     glClear(GL_COLOR_BUFFER_BIT);
  97.     glPopAttrib();
  98.  
  99.     glMatrixMode(GL_PROJECTION);
  100.     glLoadIdentity();
  101.     xoffset = yoffset = 0;
  102.     if (clipped) {
  103.     glViewport(x+boxW/2, y+boxH/2, boxW/2, boxH/2);
  104.     glOrtho(0, boxW/2, 0, boxH/2, -1.0, 1.0);
  105.     } else {
  106.     if (fastest2D) {
  107.         xoffset = x + boxW/2;
  108.         yoffset = y + boxH/2;
  109.         glViewport(0, 0, W, H);
  110.         glOrtho(0, W, 0, H, -1, 1);
  111.     } else {
  112.         glViewport(x, y, boxW, boxH);
  113.         glOrtho(-boxW/2, boxW/2, -boxH/2, boxH/2, -1.0, 1.0);
  114.     }
  115.     }
  116.     glMatrixMode(GL_MODELVIEW);
  117.  
  118.     glDrawBuffer(drawBuffer);
  119. }
  120.  
  121. static void myVertex(float x, float y)
  122. {
  123.     if (fastest2D) {
  124.     x += xoffset;
  125.     y += yoffset;
  126.     }
  127.     if (randomVertex) {
  128.     switch(random() % 3) {
  129.       case 0:
  130.         glVertex2f(x,y);
  131.         break;
  132.       case 1:
  133.         glVertex3f(x,y,0);
  134.         break;
  135.       case 2:
  136.         glVertex4f(x,y,0,1);
  137.         break;
  138.     }
  139.     } else {
  140.     glVertex2f(x,y);
  141.     }
  142. }
  143.  
  144. static void Point(void)
  145. {
  146.     long i;
  147.  
  148.     SETCOLOR(WHITE);
  149.     glBegin(GL_POINTS);
  150.     myVertex(0, 0);
  151.     for (i = 1; i < 8; i++) {
  152.         long j = i * 2;
  153.         SETCOLOR(i);
  154.         myVertex(-j, -j);
  155.         myVertex(-j, 0);
  156.         myVertex(-j, j);
  157.         myVertex(0, j);
  158.         myVertex(j, j);
  159.         myVertex(j, 0);
  160.         myVertex(j, -j);
  161.         myVertex(0, -j);
  162.     }
  163.     glEnd();
  164. }
  165.  
  166. static void Lines(void)
  167. {
  168.     long i;
  169.  
  170.     glPushMatrix();
  171.     glTranslatef(-12, 0, 0);
  172.     for (i = 1; i < 8; i++) {
  173.     SETCOLOR(i);
  174.     glBegin(GL_LINES);
  175.         myVertex(-boxW/4, -boxH/4);
  176.         myVertex(boxW/4, boxH/4);
  177.     glEnd();
  178.     glTranslatef(4, 0, 0);
  179.     }
  180.     glPopMatrix();
  181.  
  182.     /*
  183.     ** Draw a single vertex line to make sure nothing bad happens
  184.     */
  185.     glBegin(GL_LINES);
  186.     myVertex(0, 0);
  187.     glEnd();
  188. }
  189.  
  190. static void LineStrip(void)
  191. {
  192.     glBegin(GL_LINE_STRIP);
  193.     SETCOLOR(RED);
  194.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  195.     SETCOLOR(GREEN);
  196.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  197.     SETCOLOR(BLUE);
  198.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  199.     SETCOLOR(WHITE);
  200.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  201.     glEnd();
  202.  
  203.     /*
  204.     ** Draw a single vertex line to make sure nothing bad happens
  205.     */
  206.     glBegin(GL_LINE_STRIP);
  207.     myVertex(0, 0);
  208.     glEnd();
  209. }
  210.  
  211. static void LineLoop(void)
  212. {
  213.     glBegin(GL_LINE_LOOP);
  214.     SETCOLOR(RED);
  215.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(-boxH/4));
  216.     SETCOLOR(GREEN);
  217.     myVertex(PIXEL_CENTER(-boxW/4), PIXEL_CENTER(boxH/4));
  218.     SETCOLOR(BLUE);
  219.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(boxH/4));
  220.     SETCOLOR(WHITE);
  221.     myVertex(PIXEL_CENTER(boxW/4), PIXEL_CENTER(-boxH/4));
  222.     glEnd();
  223.  
  224.     /*
  225.     ** Draw a two vertex line with XOR on to make sure that only the
  226.     ** endpoints show.  Since each line segment is drawn half-open,
  227.     ** the endpoints will not be drawn twice, thus leaving the XOR of
  228.     ** white in the color buffer.  When using an RGB color buffer, use
  229.     ** the blend function to approximate the effects of the XOR.
  230.     */
  231.     glEnable(GL_LOGIC_OP);
  232.     glEnable(GL_BLEND);
  233.     glLogicOp(GL_XOR);
  234.     glBlendFunc(GL_ONE, GL_ONE);
  235.     SETCOLOR(MAGENTA);
  236.     /* this line is vertical */
  237.     glBegin(GL_LINE_LOOP);
  238.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(-boxH/8));
  239.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8));
  240.     glEnd();
  241.     /* this line is horizontal */
  242.     glBegin(GL_LINE_LOOP);
  243.     myVertex(PIXEL_CENTER(-boxW/8), PIXEL_CENTER(boxH/8+5));
  244.     myVertex(PIXEL_CENTER(boxW/8), PIXEL_CENTER(boxH/8+5));
  245.     glEnd();
  246.     glDisable(GL_LOGIC_OP);
  247.     glDisable(GL_BLEND);
  248.  
  249.     /*
  250.     ** Draw a point at the center of the area so that we can count pixels
  251.     ** if needed.
  252.     */
  253.     SETCOLOR(GREEN);
  254.     glBegin(GL_POINTS);
  255.     myVertex(0, 0);
  256.     glEnd();
  257.  
  258.     /*
  259.     ** Draw a single vertex line to make sure nothing bad happens
  260.     */
  261.     glBegin(GL_LINE_LOOP);
  262.     myVertex(0, 0);
  263.     glEnd();
  264. }
  265.  
  266. #define OPENGL_WIDTH    48
  267. #define OPENGL_HEIGHT    13
  268. static GLubyte OpenGL_bits[] = {
  269.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 
  270.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01,
  271.    0x7f, 0xfb, 0xff, 0xff, 0xff, 0x01, 
  272.    0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
  273.    0x3e, 0x8f, 0xb7, 0xf9, 0xfc, 0x01, 
  274.    0x63, 0xdb, 0xb0, 0x8d, 0x0d, 0x00,
  275.    0x63, 0xdb, 0xb7, 0x8d, 0x0d, 0x00, 
  276.    0x63, 0xdb, 0xb6, 0x8d, 0x0d, 0x00,
  277.    0x63, 0x8f, 0xf3, 0xcc, 0x0d, 0x00, 
  278.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0a,
  279.    0x63, 0x00, 0x00, 0x0c, 0x4c, 0x0e, 
  280.    0x63, 0x00, 0x00, 0x8c, 0xed, 0x0e,
  281.    0x3e, 0x00, 0x00, 0xf8, 0x0c, 0x00, 
  282. };
  283.  
  284. static void Bitmap(void)
  285. {
  286.     static const long xOrigin = 0;
  287.     static const long yOrigin = 3;
  288.  
  289.     /*
  290.     ** Draw some lines showing the left and bottom edges of the bitmap.
  291.     ** The red line is the vertical left edge of the bitmap.  The blue
  292.     ** line is the horizontal bottom edge of the bitmap.  The yellow line
  293.     ** is the horizontal base line of the bitmap.  The green lines mark
  294.     ** where the rasterpos will translate to. Take into account the x
  295.     ** origin.
  296.     */
  297.     glBegin(GL_LINES);
  298.     SETCOLOR(GREEN);
  299.     myVertex(-boxW/2, 0);
  300.     myVertex(boxW/2, 0);
  301.     myVertex(0, -boxH/2);
  302.     myVertex(0, boxH/2);
  303.     SETCOLOR(RED);
  304.     myVertex(-xOrigin, -yOrigin);
  305.     myVertex(-xOrigin, -yOrigin+OPENGL_HEIGHT);
  306.     SETCOLOR(BLUE);
  307.     myVertex(-xOrigin, -yOrigin);
  308.     myVertex(-xOrigin+OPENGL_WIDTH, -yOrigin);
  309.     glEnd();
  310.  
  311.     SETCOLOR(GREEN);
  312.  
  313.     glPixelStorei(GL_UNPACK_LSB_FIRST, GL_TRUE);
  314.     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  315.  
  316.     glRasterPos2i(xoffset, yoffset);
  317.     glBitmap(OPENGL_WIDTH, OPENGL_HEIGHT, xOrigin, yOrigin, 0.0, 0.0, 
  318.         OpenGL_bits);
  319. }
  320.  
  321. static void Triangles(void)
  322. {
  323.     glBegin(GL_TRIANGLES);
  324.     SETCOLOR(GREEN);
  325.     myVertex(-boxW/4, -boxH/4);
  326.     SETCOLOR(RED);
  327.     myVertex(-boxW/8, -boxH/16);
  328.     SETCOLOR(BLUE);
  329.     myVertex(boxW/8, -boxH/16);
  330.  
  331.     SETCOLOR(GREEN);
  332.     myVertex(-boxW/4, boxH/4);
  333.     SETCOLOR(RED);
  334.     myVertex(-boxW/8, boxH/16);
  335.     SETCOLOR(BLUE);
  336.     myVertex(boxW/8, boxH/16);
  337.     glEnd();
  338.  
  339.     /*
  340.     ** Generate a 2 vertex triangle that should draw nothing
  341.     */
  342.     glBegin(GL_TRIANGLES);
  343.     myVertex(0, 0);
  344.     myVertex(-100, 100);
  345.     glEnd();
  346. }
  347.  
  348. static void TriangleStrip(void)
  349. {
  350.     glBegin(GL_TRIANGLE_STRIP);
  351.     SETCOLOR(GREEN);
  352.     myVertex(-boxW/4, -boxH/4);
  353.     SETCOLOR(RED);
  354.     myVertex(-boxW/4, boxH/4);
  355.     SETCOLOR(BLUE);
  356.     myVertex(0, -boxH/4);
  357.     SETCOLOR(WHITE);
  358.     myVertex(0, boxH/4);
  359.     SETCOLOR(CYAN);
  360.     myVertex(boxW/4, -boxH/4);
  361.     SETCOLOR(YELLOW);
  362.     myVertex(boxW/4, boxH/4);
  363.     glEnd();
  364.  
  365.     /*
  366.     ** Generate a 2 vertex triangle strip that should draw nothing
  367.     */
  368.     glBegin(GL_TRIANGLE_STRIP);
  369.     myVertex(0, 0);
  370.     myVertex(-100, 100);
  371.     glEnd();
  372. }
  373.  
  374. static void TriangleFan(void)
  375. {
  376.     long x0, x1, x2, x3;
  377.     long y0, y1, y2, y3;
  378.     long vx[8][2];
  379.     long i;
  380.  
  381.     /*
  382.     ** Construct an 8 sided convex polygon that is almost an octahedron
  383.     */
  384.     y0 = -boxH/4;
  385.     y1 = y0 + boxH/2/3;
  386.     y2 = y1 + boxH/2/3;
  387.     y3 = boxH/4;
  388.     x0 = -boxW/4;
  389.     x1 = x0 + boxW/2/3;
  390.     x2 = x1 + boxW/2/3;
  391.     x3 = boxW/4;
  392.  
  393.     vx[0][0] = x0; vx[0][1] = y1;
  394.     vx[1][0] = x0; vx[1][1] = y2;
  395.     vx[2][0] = x1; vx[2][1] = y3;
  396.     vx[3][0] = x2; vx[3][1] = y3;
  397.     vx[4][0] = x3; vx[4][1] = y2;
  398.     vx[5][0] = x3; vx[5][1] = y1;
  399.     vx[6][0] = x2; vx[6][1] = y0;
  400.     vx[7][0] = x1; vx[7][1] = y0;
  401.  
  402.     /*
  403.     ** Draw the polygon, shaded.  This will draw the same shape that the
  404.     ** polygon test draws, except that when flat shaded it should draw
  405.     ** entirely white.  When smooth shaded it will shade differently
  406.     ** than the polygon test.
  407.     */
  408.     glBegin(GL_TRIANGLE_FAN);
  409.     SETCOLOR(WHITE);
  410.     myVertex(0, 0);
  411.     for (i = 0; i < 8; i++) {
  412.         SETCOLOR(7-i);
  413.         myVertex(vx[i][0], vx[i][1]);
  414.     }
  415.     glEnd();
  416.  
  417.     /*
  418.     ** Generate a 2 vertex triangle fan that should draw nothing
  419.     */
  420.     glBegin(GL_TRIANGLE_FAN);
  421.     myVertex(0, 0);
  422.     myVertex(-100, 100);
  423.     glEnd();
  424. }
  425.  
  426. static void Rect(void)
  427. {
  428.     SETCOLOR(GREEN);
  429.     glRecti(xoffset-boxW/4, yoffset-boxH/4, xoffset+boxW/4, yoffset+boxH/4);
  430. }
  431.  
  432. static void Polygon(void)
  433. {
  434.     long x0, x1, x2, x3;
  435.     long y0, y1, y2, y3;
  436.     long vx[8][2];
  437.     long i;
  438.  
  439.     /*
  440.     ** Construct an 8 sided convex polygon that is almost an octahedron
  441.     */
  442.     y0 = -boxH/4;
  443.     y1 = y0 + boxH/2/3;
  444.     y2 = y1 + boxH/2/3;
  445.     y3 = boxH/4;
  446.     x0 = -boxW/4;
  447.     x1 = x0 + boxW/2/3;
  448.     x2 = x1 + boxW/2/3;
  449.     x3 = boxW/4;
  450.  
  451.     vx[0][0] = x0; vx[0][1] = y1;
  452.     vx[1][0] = x0; vx[1][1] = y2;
  453.     vx[2][0] = x1; vx[2][1] = y3;
  454.     vx[3][0] = x2; vx[3][1] = y3;
  455.     vx[4][0] = x3; vx[4][1] = y2;
  456.     vx[5][0] = x3; vx[5][1] = y1;
  457.     vx[6][0] = x2; vx[6][1] = y0;
  458.     vx[7][0] = x1; vx[7][1] = y0;
  459.  
  460.     /*
  461.     ** Draw the polygon, shaded.
  462.     */
  463.     glBegin(GL_POLYGON);
  464.     for (i = 0; i < 8; i++) {
  465.         SETCOLOR(7-i);
  466.         myVertex(vx[i][0], vx[i][1]);
  467.     }
  468.     glEnd();
  469.  
  470.     /*
  471.     ** Generate a 2 vertex polygon that should draw nothing
  472.     */
  473.     glBegin(GL_POLYGON);
  474.     myVertex(0, 0);
  475.     myVertex(100, 100);
  476.     glEnd();
  477. }
  478.  
  479. static void Quads(void)
  480. {
  481.     glBegin(GL_QUADS);
  482.     SETCOLOR(GREEN);
  483.     myVertex(-boxW/4, -boxH/4);
  484.     SETCOLOR(RED);
  485.     myVertex(-boxW/8, -boxH/16);
  486.     SETCOLOR(BLUE);
  487.     myVertex(boxW/8, -boxH/16);
  488.     SETCOLOR(WHITE);
  489.     myVertex(boxW/4, -boxH/4);
  490.  
  491.     SETCOLOR(GREEN);
  492.     myVertex(-boxW/4, boxH/4);
  493.     SETCOLOR(RED);
  494.     myVertex(-boxW/8, boxH/16);
  495.     SETCOLOR(BLUE);
  496.     myVertex(boxW/8, boxH/16);
  497.     SETCOLOR(WHITE);
  498.     myVertex(boxW/4, boxH/4);
  499.     glEnd();
  500.  
  501.     /*
  502.     ** Generate a 3 vertex quad that should draw nothing
  503.     */
  504.     glBegin(GL_QUADS);
  505.     myVertex(0, 0);
  506.     myVertex(100, 100);
  507.     myVertex(-100, 100);
  508.     glEnd();
  509. }
  510.  
  511. static void QuadStrip(void)
  512. {
  513.     glBegin(GL_QUAD_STRIP);
  514.     SETCOLOR(GREEN);
  515.     myVertex(-boxW/4, -boxH/4);
  516.     SETCOLOR(RED);
  517.     myVertex(-boxW/4, boxH/4);
  518.     SETCOLOR(BLUE);
  519.     myVertex(0, -boxH/4);
  520.     SETCOLOR(WHITE);
  521.     myVertex(0, boxH/4);
  522.     SETCOLOR(CYAN);
  523.     myVertex(boxW/4, -boxH/4);
  524.     SETCOLOR(YELLOW);
  525.     myVertex(boxW/4, boxH/4);
  526.     glEnd();
  527.  
  528.     /*
  529.     ** Generate a 3 vertex quad strip that should draw nothing
  530.     */
  531.     glBegin(GL_QUAD_STRIP);
  532.     myVertex(0, 0);
  533.     myVertex(100, 100);
  534.     myVertex(-100, 100);
  535.     glEnd();
  536. }
  537.  
  538. static void RotateColorMask(void)
  539. {
  540.     static long rotation=0;
  541.     
  542.     rotation = (rotation + 1) & 0x3;
  543.     switch (rotation) {
  544.       case 0:
  545.     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
  546.     glIndexMask( 0xff );
  547.     break;
  548.       case 1:
  549.     /* mask off red */
  550.     glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
  551.     glIndexMask( 0xfe );
  552.     break;
  553.       case 2:
  554.     /* mask off green */
  555.     glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
  556.     glIndexMask( 0xfd );
  557.     break;
  558.       case 3:
  559.     /* mask off blue */
  560.     glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
  561.     glIndexMask( 0xfb );
  562.     break;
  563.     }
  564. }
  565.  
  566. static void DoTests(void)
  567. {
  568.     Viewport(0, 0); Point();
  569.     Viewport(0, 1); Lines();
  570.     Viewport(0, 2); LineStrip();
  571.     Viewport(0, 3); LineLoop();
  572.  
  573.     Viewport(1, 0); Bitmap();
  574.     Viewport(1, 1); TriangleFan();
  575.     Viewport(1, 2); Triangles();
  576.     Viewport(1, 3); TriangleStrip();
  577.  
  578.     Viewport(2, 0); Rect();
  579.     Viewport(2, 1); Polygon();
  580.     Viewport(2, 2); Quads();
  581.     Viewport(2, 3); QuadStrip();
  582.  
  583.     glFlush();
  584. }
  585.  
  586. static void Usage(void)
  587. {
  588.     printf("Usage: tprim [-c]\n");
  589.     printf("   -c:  Run in color index mode\n");
  590.     exit(-1);
  591. }
  592.  
  593. static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg)
  594. {
  595.     if ((e->type == MapNotify) && (e->xmap.window == (Window)arg)) {
  596.     return GL_TRUE;
  597.     }
  598.     return GL_FALSE;
  599. }
  600.  
  601. int main(int argc, char** argv)
  602. {
  603.     XVisualInfo *vi;
  604.     Display *dpy;
  605.     Colormap cmap;
  606.     Window window;
  607.     XSetWindowAttributes swa;
  608.     GLXContext cx;
  609.     XEvent event;
  610.     GLboolean needDisplay;
  611.     XColor white;
  612.     char *geometry = NULL;
  613.     XSizeHints sizehints;
  614.     int i;
  615.  
  616.     srandom(time(NULL));
  617.     rgb = 1;
  618.     for (i = 1; i < argc; i++) {
  619.     if (!strcmp(argv[i], "-geometry")) {
  620.         i++;
  621.         geometry = argv[i];
  622.     } else if (argv[i][0] == '-') {
  623.             switch (argv[i][1]) {
  624.               case 'c':
  625.                 rgb = GL_FALSE;
  626.                 break;
  627.               default:
  628.                 Usage();
  629.             }
  630.         } else {
  631.             Usage();
  632.         }
  633.     }
  634.  
  635.     dpy = XOpenDisplay(0);
  636.     if (!dpy) {
  637.     fprintf(stderr, "Can't connect to display \"%s\"\n", getenv("DISPLAY"));
  638.     return -1;
  639.     }
  640.  
  641.     vi = glXChooseVisual(dpy, DefaultScreen(dpy),
  642.              rgb ? RGB_attributes : CI_attributes);
  643.     if (!vi) {
  644.     fprintf(stderr, "No singlebuffered rgba visual on \"%s\"\n",
  645.         getenv("DISPLAY"));
  646.     return -1;
  647.     }
  648.  
  649.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual,
  650.                rgb ? AllocNone : AllocAll);
  651.     if (rgb) {
  652.     white.red = ~0;
  653.     white.green = ~0;
  654.     white.blue = ~0;
  655.     XAllocColor(dpy, cmap, &white);
  656.     swa.background_pixel = white.pixel;
  657.     } else {
  658.     swa.background_pixel = 7;
  659.     }
  660.  
  661.     if (!rgb) {
  662.     XColor buf;
  663.     int i;
  664.  
  665.     buf.flags = DoRed | DoGreen | DoBlue;
  666.  
  667.     /* Init color map */
  668.     for (i=0; i<16; i++) {
  669.         buf.pixel = i;
  670.         buf.blue = (i & 4) ? 65535 : 0;
  671.         buf.green = (i & 2) ? 65535 : 0;
  672.         buf.red = (i & 1) ? 65535 : 0;
  673.         if (i > 8) {
  674.         buf.red /= 2;
  675.         buf.green /= 2;
  676.         buf.blue /= 2;
  677.         }
  678.         XStoreColor(dpy, cmap, &buf);
  679.     }
  680.     }
  681.  
  682.     sizehints.flags = PPosition | PSize;
  683.     sizehints.width = W;
  684.     sizehints.height = H;
  685.     sizehints.x = 10;
  686.     sizehints.y = 10;
  687.     if(geometry) {
  688.     int flags, x, y, width, height;
  689.  
  690.     flags = XParseGeometry(geometry, &x, &y,
  691.                    (unsigned int *)&width,
  692.                    (unsigned int *)&height);
  693.         if(WidthValue & flags) {
  694.         sizehints.flags |= USSize;
  695.         sizehints.width = width;
  696.         W = width;
  697.     }
  698.     if(HeightValue & flags) {
  699.         sizehints.flags |= USSize;
  700.         sizehints.height = height;
  701.         H = height;
  702.     }
  703.     if(XValue & flags) {
  704.         if(XNegative & flags)
  705.         x = DisplayWidth(dpy, DefaultScreen(dpy)) + x 
  706.             - sizehints.width;
  707.             sizehints.flags |= USPosition;
  708.         sizehints.x = x;
  709.     }
  710.     if(YValue & flags) {
  711.         if(YNegative & flags)
  712.         y = DisplayHeight(dpy, DefaultScreen(dpy)) + y 
  713.             - sizehints.height;
  714.             sizehints.flags |= USPosition;
  715.         sizehints.y = y;
  716.     }
  717.     }
  718.     swa.border_pixel = 0;
  719.     swa.background_pixel = white.pixel;
  720.     swa.colormap = cmap;
  721.     swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask
  722.     | KeyReleaseMask;
  723.     window = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
  724.                            sizehints.x, sizehints.y,
  725.                sizehints.width, sizehints.height,
  726.                0, vi->depth, InputOutput, vi->visual,
  727.                CWBackPixel|CWBorderPixel|CWColormap|CWEventMask,
  728.                &swa);
  729.     XSetStandardProperties(dpy, window, rgb ? "tprim RGB" : "tprim CI", "tprim",
  730.                            None, argv, argc, &sizehints);
  731.     XSetWMColormapWindows(dpy, window, &window, 1);
  732.     XMapWindow(dpy, window);
  733.     XIfEvent(dpy, &event, WaitForMapNotify, (char*)window);
  734.  
  735.     cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
  736.     if (!glXMakeCurrent(dpy, window, cx)) {
  737.     fprintf(stderr, "Can't make window current to context\n");
  738.     return -1;
  739.     }
  740.  
  741.     if (rgb) {
  742.     glClearColor(1, 1, 1, 1);
  743.     } else {
  744.     glClearIndex(7);
  745.     }
  746.     glClear(GL_COLOR_BUFFER_BIT);
  747.     if (rgb) {
  748.     glClearColor(0, 0, 0, 0);
  749.     } else {
  750.     glClearIndex(0);
  751.     }
  752.  
  753.     needDisplay = GL_TRUE;
  754.     for (;;) {
  755.     do {
  756.         XNextEvent(dpy, &event);
  757.         switch (event.type) {
  758.           case Expose:
  759.         needDisplay = GL_TRUE;
  760.         break;
  761.           case ConfigureNotify:
  762.         W = event.xconfigure.width;
  763.         H = event.xconfigure.height;
  764.         needDisplay = GL_TRUE;
  765.         break;
  766.           case KeyPress:
  767.         {
  768.             char buf[100];
  769.             int rv;
  770.             KeySym ks;
  771.  
  772.             rv = XLookupString(&event.xkey, buf, sizeof(buf), &ks, 0);
  773.             switch (ks) {
  774.               case XK_F:
  775.               case XK_f:
  776.             glShadeModel(GL_FLAT);
  777.             needDisplay = GL_TRUE;
  778.             break;
  779.               case XK_S:
  780.               case XK_s:
  781.             glShadeModel(GL_SMOOTH);
  782.             needDisplay = GL_TRUE;
  783.             break;
  784.               case XK_P:
  785.               case XK_p:
  786.             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  787.             needDisplay = GL_TRUE;
  788.             break;
  789.               case XK_L:
  790.               case XK_l:
  791.             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  792.             needDisplay = GL_TRUE;
  793.             break;
  794.               case XK_C:
  795.               case XK_c:
  796.             RotateColorMask();
  797.             needDisplay = GL_TRUE;
  798.             break;
  799.               case XK_B:
  800.               case XK_b:
  801.             switch(drawBuffer) {
  802.               case GL_FRONT:
  803.                 drawBuffer = GL_NONE;
  804.                 printf("Drawing to GL_NONE.\n");
  805.                 break;
  806.               case GL_NONE:
  807.                 drawBuffer = GL_FRONT;
  808.                 printf("Drawing to GL_FRONT.\n");
  809.                 break;
  810.             }
  811.             needDisplay = GL_TRUE;
  812.             break;
  813.               case XK_R:
  814.               case XK_r:
  815.             randomVertex = 1-randomVertex;
  816.             needDisplay = GL_TRUE;
  817.             break;
  818.               case XK_Q:
  819.               case XK_q:
  820.             clipped = 1-clipped;
  821.             fastest2D = 0;
  822.             needDisplay = GL_TRUE;
  823.             break;
  824.               case XK_2:
  825.             fastest2D = 1-fastest2D;
  826.             clipped = 0;
  827.             needDisplay = GL_TRUE;
  828.             break;
  829.               case XK_Escape:
  830.             return 0;
  831.             }
  832.         }
  833.         break;
  834.         }
  835.     } while (XPending(dpy) != 0);
  836.  
  837.     if (needDisplay) {
  838.         needDisplay = GL_FALSE;
  839.         DoTests();
  840.     }
  841.     }
  842. }
  843.